#include"preCmpH.h"
#include"UIUtilities.h"

GLuint _shaderFromFile(const char* path,GLenum type)
{
	std::ifstream file(path); // deschide fisierul
	if(!file.is_open()) // verifica daca fisierul a fost deschis cu succes
	{
        std::cout << "Error in opening file " << path <<'\n';
		return 1;
	}
	// trece continutul fisierului intr-un string
    std::stringstream fileData;
	fileData << file.rdbuf();
	file.close();
	std::string text = fileData.str();
	const char* shaderCode = text.c_str();

	GLuint shader = glCreateShader(type); // creaza un shader
    glShaderSource(shader, 1, &shaderCode, NULL); // asociaza shaderul cu string obtinut din fisier

    int compiled;
	glCompileShader(shader); // compileaza shaderul
	glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
	if(compiled == 0) // verifica daca shaderul a fost compilat cu succes
	{
		std::cout << "Shader not compiled." <<'\n';
		int infoLogLen = 0;
        int charsWritten = 0;
        GLchar *infoLog;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen);
        if (infoLogLen > 0)
        {
            infoLog = new GLchar[infoLogLen];
            glGetShaderInfoLog(shader, infoLogLen, &charsWritten, infoLog);
			// afiseaza raportul primit
            std::cout << "InfoLog : " << '\n' << infoLog << '\n';
            delete [] infoLog;
        }
		// sterge shaderul
		glDeleteShader(shader);
	}
	return shader;
}
GLuint ShaderProgram(const char* vertexShaderFile, const char* fragmentShaderFile)
{
	GLuint shaderProgram = glCreateProgram(); // creaza programul
	GLuint vertexShader = _shaderFromFile(vertexShaderFile,GL_VERTEX_SHADER); // incarca vertex shader-ul din fisierul specificat
	GLuint fragmentShader = _shaderFromFile(fragmentShaderFile,GL_FRAGMENT_SHADER); // incarca fragment shader-ul din fisierul specificat

	glAttachShader(shaderProgram, vertexShader); // ataseaza vertex shader-ul la program
	glAttachShader(shaderProgram, fragmentShader); // ataseaza fragment shader-ul la program

	glLinkProgram(shaderProgram); // executa operatia de link-are a programului

	GLint IsLinked;
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, (GLint *)&IsLinked);
	if(IsLinked== 0) // verifica daca programul a fost link-at cu succes
	{
		std::cout << "Failed to link shader." << '\n';

		GLint maxLength;
		glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &maxLength);
		if(maxLength > 0)
		{
			char *pLinkInfoLog = new char[maxLength];
			glGetProgramInfoLog(shaderProgram, maxLength, &maxLength, pLinkInfoLog);
			std::cout << pLinkInfoLog << '\n';
			delete [] pLinkInfoLog;
		}
		// sterge toate resursele alocate
		glDetachShader(shaderProgram, vertexShader);
		glDetachShader(shaderProgram, fragmentShader);
		glDeleteShader(vertexShader);
		vertexShader = 0;
		glDeleteShader(fragmentShader);
		fragmentShader = 0;
		glDeleteProgram(shaderProgram);
		shaderProgram = 0;
	}
	return shaderProgram;
}

UIPoint::UIPoint()
	: x_(0)
	, y_(0)
{}
UIPoint::UIPoint(const UIPoint& p) 
	: x_(p.x_)
	, y_(p.y_)
{}
UIPoint& UIPoint::operator= (const UIPoint& p)
{
	if(this == &p)
		return *this;
	x_ = p.x_;
	y_ = p.y_;
	return *this;
}

UISize::UISize()
	: w_(0)
	, h_(0)
{}
UISize::UISize(const UISize& s)
	: w_(s.w_)
	, h_(s.h_)
{}
UISize& UISize::operator= (const UISize& s)
{
	if(this == &s)
		return *this;
	w_ = s.w_;
	h_ = s.h_;
	return *this;
}